#include <iostream>
#include <memory>

using std::cout;
using std::endl;
using std::unique_ptr;

//抽象的组件类
class Component
{
public:
    //声明纯虚函数，也就操作方式
    virtual void operation()  = 0;
    virtual ~Component(){}
};

//具体的组件类
class ConcreteComponent
: public Component
{
public:
    virtual void operation()  override
    {
        cout << "ConcreteComponent实现具体的组件操作" << endl;
    }
};

class Decorator
: public Component
{
public:
    void setComponent(Component *pcom)
    {
        _pcom = pcom;
    }

    virtual void operation()  override
    {
        if(_pcom)
        {
            _pcom->operation();//肯定有多态
        }
    }

private:
    Component *_pcom;
};

class ConcreteDecoratorA
: public Decorator
{
public:
    ConcreteDecoratorA()
    {
        cout << "ConcreteDecoratorA()" << endl;
    }

    virtual void operation()  override
    {
        Decorator::operation();//显示调用基类中的operation操作
        addBehaviore();
    }

    void addBehaviore()
    {
        cout << "具体的装饰器A的行为"  << endl;
    }

    ~ConcreteDecoratorA()
    {
        cout << "~ConcreteDecoratorA()" << endl;
    }
};

class ConcreteDecoratorB
: public Decorator
{
public:
    ConcreteDecoratorB()
    {
        cout << "ConcreteDecoratorB()" << endl;
    }

    virtual void operation()  override
    {
        Decorator::operation();//显示调用基类中的operation操作
        addBehaviore();
    }

    void addBehaviore()
    {
        cout << "具体的装饰器B的行为"  << endl;
    }

    ~ConcreteDecoratorB()
    {
        cout << "~ConcreteDecoratorB()" << endl;
    }
};

void test()
{
    // 创建两个具体的装饰器对象
    // 基类指针pda指向ConcreteDecoratorA
    // 基类指针pdb指向ConcreteDecoratorB
    unique_ptr<Decorator> pda(new ConcreteDecoratorA());
    unique_ptr<Decorator> pdb(new ConcreteDecoratorB());

    // 创建具体的组件对象i
    // 基类指针pcom指向ConcreteComponent
    unique_ptr<Component> pcom(new ConcreteComponent());

    // SetComponent没有覆写，因此依然调用基类setComponent
    // 将pda的_comp指针指向pcom
    // 将pdb的_comp指针指向pda
    pda->setComponent(pcom.get());
    pdb->setComponent(pda.get());

    // 三者是链式，还是指向同一地址呢？
    // 输出指针地址
    cout << "pcom地址: " << pcom.get() << endl;
    cout << "pda地址: " << pda.get() << endl; 
    cout << "pdb地址: " << pdb.get() << endl;

    // pdb执行operation()，走派生类ConcreteDecoratorB多态
    // 派生类中调用基类的operation()，pdb的_pcom指针存在且指向pda，走派生类ConCreteDecoratorA多态
    // 派生类中调用基类的operation()，pda的_pcom指针存在且指向pcom，走派生类ConCreteComponent多态
    pdb->operation();
}

int main(int argc, char *argv[])
{
    test();
    return 0;
}


